home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / SOCKET.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-18  |  51.6 KB  |  2,199 lines

  1. /* Application programming interface routines - based loosely on the
  2.  * "socket" model in Berkeley UNIX.
  3.  *
  4.  * Copyright 1991 Phil Karn, KA9Q
  5.  */
  6. #include "global.h"
  7. #include <time.h>
  8. #ifndef MSDOS
  9. #include <stdarg.h>
  10. #endif
  11. #include "mbuf.h"
  12. #include "netuser.h"
  13. #include "iface.h"
  14. #include "udp.h"
  15. #include "netrom.h"
  16. #include "lzw.h"
  17.  
  18. #if !defined(_lint)
  19. static char rcsid[] OPTIONAL = "$Id: socket.c,v 1.24 1997/08/19 01:19:22 root Exp root $";
  20. #endif
  21.  
  22. /* In connect(), accept() and recv_mbuf()
  23.  * the noblock options have been removed, since they never occur anyway.
  24.  * If you want then back, do a '#define useblock 1'
  25.  * The socket's 'noblock' parameter is now only effective for sending
  26.  * data; ie if set, only sending data will not block. - WG7J
  27.  */
  28. #define useblock 1
  29.  
  30.  
  31. static void autobind (int s, int af);
  32. static int checkaddr (int type, char *name, int namelen);
  33. static void rip_recv (struct raw_ip * rp);
  34. static void s_trcall (struct tcb * tcb, int16 cnt);
  35. static void s_tscall (struct tcb * tcb, int old, int new);
  36. static void s_ttcall (struct tcb * tcb, int16 cnt);
  37. static void s_urcall (struct iface * iface, struct udp_cb * udp, int16 cnt);
  38. static void trdiscard (struct tcb * tcb, int16 cnt);
  39.  
  40. #ifdef    NETROM
  41. static void s_nrcall (struct nr4cb * cb, int16 cnt);
  42. static void s_nscall (struct nr4cb * cb, int old, int new);
  43. static void s_ntcall (struct nr4cb * cb, int16 cnt);
  44. #endif
  45.  
  46. static int16 Lport = 1024;
  47.  
  48. const char *Socktypes[] =
  49. {
  50.     "Not Used",
  51.     "TCP",
  52.     "UDP",
  53.     "AX25 I",
  54.     "AX25 UI",
  55.     "Raw IP",
  56.     "NETROM3",
  57.     "NETROM",
  58.     "Loc St",
  59.     "Loc Dg"
  60. };
  61.  
  62.  
  63. char Badsocket[] = "Bad socket";
  64. struct usock *Usock;        /* Socket entry array */
  65. int Nusock = DEFNSOCK;        /* Number of socket entries */
  66.  
  67. /* The following two variables are needed because there can be only one
  68.  * socket listening on each of the AX.25 modes (I and UI)
  69.  */
  70. #ifdef    AX25
  71. int Axi_sock = -1;        /* Socket number listening for AX25 connections */
  72.  
  73. #if 0
  74. int Axui_sock = -1;        /* Socket number listening for AX25 UI frames */
  75. static struct mbuf *Bcq;    /* Queue of incoming UI frames */
  76.  
  77. /* Function that handles incoming UI frames from lapb.c */
  78. void
  79. beac_input (struct iface *iface, char *src, struct mbuf *bp)
  80. {
  81. struct mbuf *hdr;
  82. struct sockaddr_ax *sax;
  83.  
  84.     if (Axui_sock == -1)     /* Nobody there to read it */
  85.         free_p (bp);
  86.     else {
  87.         if ((hdr = pushdown (NULLBUF, sizeof (struct sockaddr_ax))) == NULLBUF) {
  88.             free_p (bp);
  89.             return;
  90.         }
  91.         sax = (struct sockaddr_ax *) hdr->data;
  92.         sax->sax_family = AF_AX25;
  93.         memcpy (sax->ax25_addr, src, AXALEN);
  94.         strncpy (sax->iface, iface->name, ILEN - 1);
  95.         hdr->next = bp;
  96.         enqueue (&Bcq, hdr);
  97.     }
  98. }
  99. #endif
  100. #endif /* AX.25 */
  101.  
  102.  
  103.  
  104. /* Initialize user socket array */
  105. void
  106. sockinit (void)
  107. {
  108.     if (Usock != NULLUSOCK)
  109.         return;        /* Already initialized */
  110.     Usock = (struct usock *) callocw ((unsigned) Nusock, sizeof (struct usock));
  111. }
  112.  
  113.  
  114.  
  115. /* Create a user socket, return socket index
  116.  * The mapping to actual protocols is as follows:
  117.  *
  118.  *
  119.  * ADDRESS FAMILY    Stream        Datagram    Raw        Seq. Packet
  120.  *
  121.  * AF_INET        TCP        UDP        IP
  122.  * AF_AX25        I-frames    UI-frames
  123.  * AF_NETROM                        NET/ROM L3  NET/ROM L4
  124.  * AF_LOCAL        stream loopback    packet loopback
  125.  */
  126. int
  127. socket (
  128. int af,                /* Address family */
  129. int type,            /* Stream or datagram */
  130. int protocol            /* Used for raw IP sockets */
  131. ) {
  132. register struct usock *up;
  133. int s;
  134.  
  135.     for (up = Usock; up < &Usock[Nusock]; up++)
  136.         if (up->type == NOTUSED)
  137.             break;
  138.  
  139.     if (up == &Usock[Nusock]) {
  140.         /* None left */
  141.         errno = EMFILE;
  142.         return -1;
  143.     }
  144.     /* set the time the socket was created - WG7J */
  145.     up->created = time (NULL);
  146.     up->refcnt = 1;
  147.     s = up - Usock + SOCKBASE;
  148.     errno = 0;
  149.     up->look = NULLPROC;
  150.     up->noblock = SOCK_BLOCK;
  151.     up->rdysock = -1;
  152.     up->cb.p = NULLCHAR;
  153.     up->peername = up->name = NULLCHAR;
  154.     up->namelen = up->peernamelen = 0;
  155.     up->owner = Curproc;
  156.     up->obuf = NULLBUF;
  157.     up->insertbuf = NULLCHAR;
  158.     up->insertptr = NULLCHAR;
  159.     memset (up->errcodes, 0, sizeof (up->errcodes));
  160.     memset (up->eol, 0, sizeof (up->eol));
  161.     up->flush = '\n';    /* default is line buffered */
  162.     switch (af) {
  163.         case AF_LOCAL:
  164.             up->cb.local = (struct loc *) callocw (1, sizeof (struct loc));
  165.  
  166.             up->cb.local->peer = up;    /* connect to self */
  167.             switch (type) {
  168.                 case SOCK_STREAM:
  169.                     up->type = TYPE_LOCAL_STREAM;
  170.                     up->cb.local->hiwat = LOCSFLOW;
  171.                     break;
  172.                 case SOCK_DGRAM:
  173.                     up->type = TYPE_LOCAL_DGRAM;
  174.                     up->cb.local->hiwat = LOCDFLOW;
  175.                     break;
  176.                 default:
  177.                     free (up->cb.local);
  178.                     errno = ESOCKTNOSUPPORT;
  179.                     break;
  180.             }
  181.             break;
  182. #ifdef    AX25
  183.         case AF_AX25:
  184.             switch (type) {
  185.                 case SOCK_STREAM:
  186.                     up->type = TYPE_AX25I;
  187.                     break;
  188.                 case SOCK_DGRAM:
  189.                     up->type = TYPE_AX25UI;
  190.                     break;
  191.                 default:
  192.                     errno = ESOCKTNOSUPPORT;
  193.                     break;
  194.             }
  195.             strcpy (up->eol, AX_EOL);
  196.             break;
  197. #endif
  198. #ifdef NETROM
  199.         case AF_NETROM:
  200.             switch (type) {
  201.                 case SOCK_RAW:
  202.                     up->type = TYPE_NETROML3;
  203.                     up->cb.rnr = raw_nr ((char) protocol);
  204.                     break;
  205.                 case SOCK_SEQPACKET:
  206.                     up->type = TYPE_NETROML4;
  207.                     break;
  208.                 default:
  209.                     errno = ESOCKTNOSUPPORT;
  210.                     break;
  211.             }
  212.             strcpy (up->eol, AX_EOL);
  213.             break;
  214. #endif
  215.         case AF_INET:
  216.             switch (type) {
  217.                 case SOCK_STREAM:
  218.                     up->type = TYPE_TCP;
  219.                     strcpy (up->eol, INET_EOL);
  220.                     break;
  221.                 case SOCK_DGRAM:
  222.                     up->type = TYPE_UDP;
  223.                     break;
  224.                 case SOCK_RAW:
  225.                     up->type = TYPE_RAW;
  226.                     up->cb.rip = raw_ip (protocol, rip_recv);
  227.                     up->cb.rip->user = s;
  228.                     break;
  229.                 default:
  230.                     errno = ESOCKTNOSUPPORT;
  231.                     break;
  232.             }
  233.             break;
  234.         default:
  235.             errno = EAFNOSUPPORT;
  236.             break;
  237.     }
  238.     if (errno)
  239.         return -1;
  240.  
  241.     return s;
  242. }
  243.  
  244.  
  245.  
  246. /* Attach a local address/port to a socket. If not issued before a connect
  247.  * or listen, will be issued automatically
  248.  */
  249. int
  250. bind (
  251. int s,                /* Socket index */
  252. char *name,            /* Local name */
  253. int namelen            /* Length of name */
  254. ) {
  255. register struct usock *up;
  256. union sp local;
  257. struct socket lsock;
  258.  
  259.     if ((up = itop (s)) == NULLUSOCK) {
  260.         errno = EBADF;
  261.         return -1;
  262.     }
  263.     if (up->type == TYPE_LOCAL_STREAM || up->type == TYPE_LOCAL_DGRAM) {
  264.         errno = EINVAL;
  265.         return -1;
  266.     }
  267.     if (name == NULLCHAR) {
  268.         errno = EFAULT;
  269.         return -1;
  270.     }
  271.     if (up->name != NULLCHAR) {
  272.         /* Bind has already been issued */
  273.         errno = EINVAL;
  274.         return -1;
  275.     }
  276.     if (checkaddr (up->type, name, namelen) == -1) {
  277.         /* Incorrect length or family for chosen protocol */
  278.         errno = EAFNOSUPPORT;
  279.         return -1;
  280.     }
  281.     /* Stash name in an allocated block */
  282.     up->namelen = namelen;
  283.     up->name = mallocw ((unsigned) namelen);
  284.     memcpy (up->name, name, (size_t) namelen);
  285.     /* Create control block for datagram sockets */
  286.     switch (up->type) {
  287.         case TYPE_UDP:
  288.             local.in = (struct sockaddr_in *) up->name;
  289.             lsock.address = local.in->sin_addr.s_addr;
  290.             lsock.port = local.in->sin_port;
  291.             if ((up->cb.udp = open_udp (&lsock, s_urcall)) != NULLUDP)
  292.                 up->cb.udp->user = s;
  293.             else
  294.                 return -1;
  295.             break;
  296. #ifdef  notdef
  297.         case TYPE_AX25UI:
  298.             if (Axui_sock != -1) {
  299.                 errno = EADDRINUSE;
  300.                 return -1;
  301.             }
  302.             Axui_sock = s;
  303.             break;
  304. #endif
  305.         default:
  306.             break;
  307.     }
  308.     return 0;
  309. }
  310.  
  311.  
  312.  
  313. /* Post a listen on a socket */
  314. int
  315. listen (
  316. int s,                /* Socket index */
  317. int backlog            /* 0 for a single connection, 1 for multiple connections */
  318. ) {
  319. register struct usock *up;
  320. union sp local;
  321. struct socket lsock;
  322.  
  323.     if ((up = itop (s)) == NULLUSOCK) {
  324.         errno = EBADF;
  325.         return -1;
  326.     }
  327.     if (up->type == TYPE_LOCAL_STREAM || up->type == TYPE_LOCAL_DGRAM) {
  328.         errno = EINVAL;
  329.         return -1;
  330.     }
  331.     if (up->cb.p != NULLCHAR) {
  332.         errno = EISCONN;
  333.         return -1;
  334.     }
  335.     switch (up->type) {
  336.         case TYPE_TCP:
  337.             if (up->name == NULLCHAR)
  338.                 autobind (s, AF_INET);
  339.  
  340.             local.in = (struct sockaddr_in *) up->name;
  341.             lsock.address = local.in->sin_addr.s_addr;
  342.             lsock.port = local.in->sin_port;
  343.             up->cb.tcb = open_tcp (&lsock, NULLSOCK,
  344.                 backlog ? TCP_SERVER : TCP_PASSIVE, 0,
  345.                 s_trcall, s_ttcall, s_tscall, 0, s);
  346.             break;
  347. #ifdef AX25
  348.         case TYPE_AX25I:
  349.             if (up->name == NULLCHAR)
  350.                 autobind (s, AF_AX25);
  351.             if (s != Axi_sock) {
  352.                 errno = EOPNOTSUPP;
  353.                 return -1;
  354.             }
  355.             local.ax = (struct sockaddr_ax *) up->name;
  356.             up->cb.ax25 = open_ax25 (NULLIF, local.ax->ax25_addr, NULLCHAR,
  357.                 backlog ? AX_SERVER : AX_PASSIVE, 0,
  358.                 s_arcall, s_atcall, s_ascall, s);
  359.             break;
  360. #endif
  361. #ifdef NETROM
  362.         case TYPE_NETROML4:
  363.             if (up->name == NULLCHAR)
  364.                 autobind (s, AF_NETROM);
  365.             local.nr = (struct sockaddr_nr *) up->name;
  366.             up->cb.nr4 = open_nr4 (&local.nr->nr_addr, NULLNRADDR,
  367.                 backlog ? AX_SERVER : AX_PASSIVE,
  368.                 s_nrcall, s_ntcall, s_nscall, s);
  369.             break;
  370. #endif
  371.         default:
  372.             /* Listen not supported on datagram sockets */
  373.             errno = EOPNOTSUPP;
  374.             return -1;
  375.     }
  376.     return 0;
  377. }
  378.  
  379.  
  380.  
  381. /* Initiate active open. For datagram sockets, merely bind the remote address. */
  382. int
  383. connect (
  384. int s,                /* Socket index */
  385. char *peername,            /* Peer name */
  386. int peernamelen            /* Length of peer name */
  387. ) {
  388. register struct usock *up;
  389. union cb cb;
  390. union sp local, remote;
  391. struct socket lsock, fsock;
  392. #ifdef    AX25
  393. struct iface *iface;
  394. #endif
  395.  
  396.     if ((up = itop (s)) == NULLUSOCK) {
  397.         errno = EBADF;
  398.         return -1;
  399.     }
  400.     if (up->type == TYPE_LOCAL_DGRAM || up->type == TYPE_LOCAL_STREAM) {
  401.         errno = EINVAL;
  402.         return -1;
  403.     }
  404.     if (peername == NULLCHAR) {
  405.         /* Connect must specify a remote address */
  406.         errno = EFAULT;
  407.         return -1;
  408.     }
  409.     if (checkaddr (up->type, peername, peernamelen) == -1) {
  410.         errno = EAFNOSUPPORT;
  411.         return -1;
  412.     }
  413.     /* Raw socket control blocks are created in socket() */
  414.     if (up->type != TYPE_RAW && up->type != TYPE_NETROML3 &&
  415.         up->cb.p != NULLCHAR) {
  416.         errno = EISCONN;
  417.         return -1;
  418.     }
  419.     up->peername = mallocw ((unsigned) peernamelen);
  420.     memcpy (up->peername, peername, (size_t) peernamelen);
  421.     up->peernamelen = peernamelen;
  422.  
  423.     /* Set up the local socket structures */
  424.     if (up->name == NULLCHAR) {
  425.         switch (up->type) {
  426.             case TYPE_TCP:
  427.             case TYPE_UDP:
  428.             case TYPE_RAW:
  429.                 autobind (s, AF_INET);
  430.                 break;
  431. #ifdef    AX25
  432.             case TYPE_AX25I:
  433.             case TYPE_AX25UI:
  434.                 autobind (s, AF_AX25);
  435.                 break;
  436. #endif
  437. #ifdef    NETROM
  438.             case TYPE_NETROML3:
  439.             case TYPE_NETROML4:
  440.                 autobind (s, AF_NETROM);
  441.                 break;
  442. #endif
  443.             default:
  444.                 break;
  445.         }
  446.     }
  447.     switch (up->type) {
  448.         case TYPE_TCP:
  449.             /* Construct the TCP-style ports from the sockaddr structs */
  450.             local.in = (struct sockaddr_in *) up->name;
  451.             remote.in = (struct sockaddr_in *) up->peername;
  452.  
  453.             if (local.in->sin_addr.s_addr == INADDR_ANY)
  454.                 /* Choose a local address */
  455.                 local.in->sin_addr.s_addr = locaddr (remote.in->sin_addr.s_addr);
  456.  
  457.             lsock.address = local.in->sin_addr.s_addr;
  458.             lsock.port = local.in->sin_port;
  459.             fsock.address = remote.in->sin_addr.s_addr;
  460.             fsock.port = remote.in->sin_port;
  461.  
  462.             /* Open the TCB in active mode */
  463.             up->cb.tcb = open_tcp (&lsock, &fsock, TCP_ACTIVE, 0,
  464.                 s_trcall, s_ttcall, s_tscall, 0, s);
  465.  
  466.             /* Wait for the connection to complete */
  467.             while ((cb.tcb = up->cb.tcb) != NULLTCB && cb.tcb->state != TCP_ESTABLISHED) {
  468. #ifdef useblock
  469.                 if (up->noblock) {
  470.                     errno = EWOULDBLOCK;
  471.                     return -1;
  472.                 } else
  473. #endif
  474.                 if ((errno = kwait (up)) != 0)
  475.                     return -1;
  476.             }
  477.             if (cb.tcb == NULLTCB) {
  478.                 /* Probably got refused */
  479.                 free (up->peername);
  480.                 up->peername = NULLCHAR;
  481.                 errno = ECONNREFUSED;
  482.                 return -1;
  483.             }
  484.             break;
  485.         case TYPE_UDP:
  486. #ifdef    AX25
  487.         case TYPE_AX25UI:
  488. #endif
  489. #ifdef    NETROM
  490.         case TYPE_NETROML3:
  491. #endif
  492.         case TYPE_RAW:
  493.             /* Control block already created by bind() */
  494.             break;
  495. #ifdef    AX25
  496.         case TYPE_AX25I:
  497.             local.ax = (struct sockaddr_ax *) up->name;
  498.             remote.ax = (struct sockaddr_ax *) up->peername;
  499.             if ((iface = if_lookup (remote.ax->iface)) == NULLIF) {
  500.                 errno = EINVAL;
  501.                 return -1;
  502.             }
  503.             if (local.ax->ax25_addr[0] == '\0') {
  504.                 /* The local address was unspecified; set it from
  505.                  * the interface address
  506.                  */
  507.                 memcpy (local.ax->ax25_addr, iface->hwaddr, AXALEN);
  508.             }
  509.             /* If we already have an AX25 link we can use it */
  510.             if ((up->cb.ax25 = find_ax25 (local.ax->ax25_addr,
  511.                 remote.ax->ax25_addr, iface)) != NULLAX25
  512.                 && up->cb.ax25->state != LAPB_DISCONNECTED &&
  513.                 up->cb.ax25->user == -1) {
  514.                 up->cb.ax25->user = s;
  515.                 up->cb.ax25->r_upcall = s_arcall;
  516.                 up->cb.ax25->t_upcall = s_atcall;
  517.                 up->cb.ax25->s_upcall = s_ascall;
  518.                 if (up->cb.ax25->state == LAPB_CONNECTED
  519.                     || up->cb.ax25->state == LAPB_RECOVERY)
  520.                     return 0;
  521.             } else
  522.                 up->cb.ax25 = open_ax25 (iface, local.ax->ax25_addr,
  523.                     remote.ax->ax25_addr, AX_ACTIVE,
  524.                     Axwindow, s_arcall, s_atcall, s_ascall, s);
  525.  
  526.             /* Wait for the connection to complete */
  527.             while ((cb.ax25 = up->cb.ax25) != NULLAX25 && cb.ax25->state != LAPB_CONNECTED) {
  528. #ifdef useblock
  529.                 if (up->noblock) {
  530.                     errno = EWOULDBLOCK;
  531.                     return -1;
  532.                 } else
  533. #endif
  534.                 if ((errno = kwait (up)) != 0)
  535.                     return -1;
  536.             }
  537.             if (cb.ax25 == NULLAX25) {
  538.                 /* Connection probably already exists */
  539.                 free (up->peername);
  540.                 up->peername = NULLCHAR;
  541.                 errno = ECONNREFUSED;
  542.                 return -1;
  543.             }
  544.             break;
  545. #endif
  546. #ifdef    NETROM
  547.         case TYPE_NETROML4:
  548.             local.nr = (struct sockaddr_nr *) up->name;
  549.             remote.nr = (struct sockaddr_nr *) up->peername;
  550.             up->cb.nr4 = open_nr4 (&local.nr->nr_addr, &remote.nr->nr_addr,
  551.                 AX_ACTIVE, s_nrcall, s_ntcall, s_nscall, s);
  552.  
  553.             /* Wait for the connection to complete */
  554.             while ((cb.nr4 = up->cb.nr4) != NULLNR4CB && cb.nr4->state != NR4STCON) {
  555. #ifdef useblock
  556.                 if (up->noblock) {
  557.                     errno = EWOULDBLOCK;
  558.                     return -1;
  559.                 } else
  560. #endif
  561.                 if ((errno = kwait (up)) != 0)
  562.                     return -1;
  563.             }
  564.             if (cb.nr4 == NULLNR4CB) {
  565.                 /* Connection probably already exists */
  566.                 free (up->peername);
  567.                 up->peername = NULLCHAR;
  568.                 errno = ECONNREFUSED;
  569.                 return -1;
  570.             }
  571.             break;
  572. #endif
  573.         default:
  574.             break;
  575.     }
  576.     return 0;
  577. }
  578.  
  579.  
  580.  
  581. /* Wait for a connection. Valid only for connection-oriented sockets. */
  582. int
  583. accept (
  584. int s,                /* Socket index */
  585. char *peername,            /* Peer name */
  586. int *peernamelen        /* Length of peer name */
  587. ) {
  588. int i;
  589. register struct usock *up;
  590.  
  591.     if ((up = itop (s)) == NULLUSOCK) {
  592.         errno = EBADF;
  593.         return -1;
  594.     }
  595.     if (up->type == TYPE_LOCAL_DGRAM || up->type == TYPE_LOCAL_STREAM) {
  596.         errno = EINVAL;
  597.         return -1;
  598.     }
  599.     if (up->cb.p == NULLCHAR) {
  600.         errno = EOPNOTSUPP;
  601.         return -1;
  602.     }
  603.     /* Accept is valid only for stream sockets */
  604.     switch (up->type) {
  605.         case TYPE_TCP:
  606. #ifdef    AX25
  607.         case TYPE_AX25I:
  608. #endif
  609. #ifdef    NETROM
  610.         case TYPE_NETROML4:
  611. #endif
  612.             break;
  613.         default:
  614.             errno = EOPNOTSUPP;
  615.             return -1;
  616.     }
  617.     /* Wait for the state-change upcall routine to signal us */
  618.     while (up->cb.p != NULLCHAR && up->rdysock == -1) {
  619. #ifdef useblock
  620.         if (up->noblock) {
  621.             errno = EWOULDBLOCK;
  622.             return -1;
  623.         } else
  624. #endif
  625.         if ((errno = kwait (up)) != 0)
  626.             return -1;
  627.     }
  628.     if (up->cb.p == NULLCHAR) {
  629.         /* Blown away */
  630.         errno = EBADF;
  631.         return -1;
  632.     }
  633.     i = up->rdysock;
  634.     up->rdysock = -1;
  635.  
  636.     up = itop (i);
  637.     if (peername != NULLCHAR && peernamelen != NULL) {
  638.         *peernamelen = min (up->peernamelen, *peernamelen);
  639.         memcpy (peername, up->peername, (size_t) * peernamelen);
  640.     }
  641.     /* set the time this was created - WG7J */
  642.     if (up == NULLUSOCK) {
  643.         errno = EBADF;
  644.         return -1;
  645.     }
  646.     up->created = time (NULL);
  647.     return i;
  648. }
  649.  
  650.  
  651.  
  652. /* Low-level receive routine. Passes mbuf back to user; more efficient than
  653.  * higher-level functions recv() and recvfrom(). Datagram sockets ignore
  654.  * the len parameter.
  655.  */
  656. int
  657. recv_mbuf (
  658. int s,                /* Socket index */
  659. struct mbuf **bpp,        /* Place to stash receive buffer */
  660. int flags OPTIONAL,        /* Unused; will control out-of-band data, etc */
  661. char *from,            /* Peer address (only for datagrams) */
  662. int *fromlen            /* Length of peer address */
  663. ) {
  664. register struct usock *up;
  665. int cnt = 0;
  666. union cb cb;
  667. struct socket fsocket;
  668. union sp remote;
  669. struct ip ip;
  670. struct mbuf *bp = NULLBUF;
  671. #ifdef    NETROM
  672. struct nr3hdr n3hdr;
  673. #endif
  674.  
  675.     if ((up = itop (s)) == NULLUSOCK) {
  676.         errno = EBADF;
  677.         return -1;
  678.     }
  679.     if (up->ibuf != NULLBUF) {
  680.         /* Return input buffer */
  681.         cnt = len_p (up->ibuf);
  682.         if (bpp != NULLBUFP)
  683.             *bpp = up->ibuf;
  684.         else
  685.             free_p (up->ibuf);
  686.         up->ibuf = NULLBUF;
  687.         return cnt;
  688.     }
  689.     switch (up->type) {
  690.         case TYPE_LOCAL_STREAM:
  691.         case TYPE_LOCAL_DGRAM:
  692.             while (up->cb.local != NULLLOC && up->cb.local->q == NULLBUF
  693.                    && up->cb.local->peer != NULLUSOCK) {
  694. #ifdef useblock
  695.                 if (up->noblock & SOCK_NORXBLOCK) {
  696.                     errno = (Curproc->retval == EALARM) ? EALARM : EWOULDBLOCK;
  697.                     return -1;
  698.                 } else
  699. #endif
  700.                 if ((errno = kwait (up)) != 0)
  701.                     return -1;
  702.             }
  703.             if (up->cb.local == NULLLOC) {
  704.                 errno = EBADF;
  705.                 return -1;
  706.             }
  707.             if (up->cb.local->q == NULLBUF && up->cb.local->peer == NULLUSOCK) {
  708.                 errno = ENOTCONN;
  709.                 return -1;
  710.             }
  711.             /* For datagram sockets, this will return the
  712.              * first packet on the queue. For stream sockets,
  713.              * this will return everything.
  714.              */
  715.             bp = dequeue (&up->cb.local->q);
  716.             if (up->cb.local->q == NULLBUF && (up->cb.local->flags & LOC_SHUTDOWN))
  717.                 close_s (s);
  718.             ksignal (up, 0);
  719.             cnt = len_p (bp);
  720.             break;
  721.         case TYPE_TCP:
  722.             while ((cb.tcb = up->cb.tcb) != NULLTCB
  723.                 && cb.tcb->r_upcall != trdiscard
  724.                 && (cnt = recv_tcp (cb.tcb, &bp, (int16) 0)) == -1) {
  725. #ifdef useblock
  726.                 if (up->noblock & SOCK_NORXBLOCK) {
  727.                     errno = (Curproc->retval == EALARM) ? EALARM : EWOULDBLOCK;
  728.                     return -1;
  729.                 } else
  730. #endif
  731.                 if ((errno = kwait (up)) != 0)
  732.                     return -1;
  733.             }
  734.             if (cb.tcb == NULLTCB) {
  735.                 /* Connection went away */
  736.                 errno = ENOTCONN;
  737.                 return -1;
  738.             } else if (cb.tcb->r_upcall == trdiscard) {
  739.                 /* Receive shutdown has been done */
  740.                 errno = ENOTCONN;    /* CHANGE */
  741.                 return -1;
  742.             }
  743.             break;
  744.         case TYPE_UDP:
  745.             while ((cb.udp = up->cb.udp) != NULLUDP && (cnt = recv_udp (cb.udp, &fsocket, &bp)) == -1) {
  746. #ifdef useblock
  747.                 if (up->noblock & SOCK_NORXBLOCK) {
  748.                     errno = (Curproc->retval == EALARM) ? EALARM : EWOULDBLOCK;
  749.                     return -1;
  750.                 } else
  751. #endif
  752.                 if ((errno = kwait (up)) != 0)
  753.                     return -1;
  754.             }
  755.             if (cb.udp == NULLUDP) {
  756.                 /* Connection went away */
  757.                 errno = ENOTCONN;
  758.                 return -1;
  759.             }
  760.             if (from != NULLCHAR && fromlen != (int *) NULL && *fromlen >= (int) SOCKSIZE) {
  761.                 remote.in = (struct sockaddr_in *) from;
  762.                 remote.in->sin_family = AF_INET;
  763.                 remote.in->sin_addr.s_addr = fsocket.address;
  764.                 remote.in->sin_port = fsocket.port;
  765.                 *fromlen = SOCKSIZE;
  766.             }
  767.             break;
  768.         case TYPE_RAW:
  769.             while ((cb.rip = up->cb.rip) != NULLRIP && cb.rip->rcvq == NULLBUF) {
  770. #ifdef useblock
  771.                 if (up->noblock & SOCK_NORXBLOCK) {
  772.                     errno = (Curproc->retval == EALARM) ? EALARM : EWOULDBLOCK;
  773.                     return -1;
  774.                 } else
  775. #endif
  776.                 if ((errno = kwait (up)) != 0)
  777.                     return -1;
  778.             }
  779.             if (cb.rip == NULLRIP) {
  780.                 /* Connection went away */
  781.                 errno = ENOTCONN;
  782.                 return -1;
  783.             }
  784.             bp = dequeue (&cb.rip->rcvq);
  785.             (void) ntohip (&ip, &bp);
  786.  
  787.             cnt = len_p (bp);
  788.             if (from != NULLCHAR && fromlen != (int *) NULL && *fromlen >= (int) SOCKSIZE) {
  789.                 remote.in = (struct sockaddr_in *) from;
  790.                 remote.in->sin_family = AF_INET;
  791.                 remote.in->sin_addr.s_addr = ip.source;
  792.                 remote.in->sin_port = 0;
  793.                 *fromlen = SOCKSIZE;
  794.             }
  795.             break;
  796. #ifdef    AX25
  797.         case TYPE_AX25I:
  798.             while ((cb.ax25 = up->cb.ax25) != NULLAX25 && (bp = recv_ax25 (cb.ax25, (int16) 0)) == NULLBUF) {
  799. #ifdef useblock
  800.                 if (up->noblock & SOCK_NORXBLOCK) {
  801.                     errno = (Curproc->retval == EALARM) ? EALARM : EWOULDBLOCK;
  802.                     return -1;
  803.                 } else
  804. #endif
  805.                 if ((errno = kwait (up)) != 0)
  806.                     return -1;
  807.             }
  808.             if (cb.ax25 == NULLAX25) {
  809.                 /* Connection went away */
  810.                 errno = ENOTCONN;
  811.                 return -1;
  812.             }
  813.             if (bp == NULLBUF)
  814.                 return 0;
  815.             cnt = bp->cnt;
  816.             break;
  817. #ifdef notdef
  818.         case TYPE_AX25UI:
  819.             while (s == Axui_sock && Bcq == NULLBUF) {
  820. #ifdef useblock
  821.                 if (up->noblock & SOCK_NORXBLOCK) {
  822.                     errno = (Curproc->retval == EALARM) ? EALARM : EWOULDBLOCK;
  823.                     return -1;
  824.                 } else
  825. #endif
  826.                 if ((errno = kwait (&Bcq)) != 0)
  827.                     return -1;
  828.             }
  829.             if (s != Axui_sock) {
  830.                 errno = ENOTCONN;
  831.                 return -1;
  832.             }
  833.             bp = dequeue (&Bcq);
  834.  
  835.             if (from != NULLCHAR && fromlen != NULLINT
  836.                 && *fromlen >= sizeof (struct sockaddr_ax)) {
  837.                 pullup (&bp, from, sizeof (struct sockaddr_ax));
  838.                 *fromlen = sizeof (struct sockaddr_ax);
  839.             } else
  840.                 pullup (&bp, NULLCHAR, sizeof (struct sockaddr_ax));
  841.  
  842.             cnt = len_p (bp);
  843.             break;
  844. #endif /* notdef */
  845. #endif /* ax25 */
  846. #ifdef NETROM
  847.         case TYPE_NETROML3:
  848.             while ((cb.rnr = up->cb.rnr) != NULLRNR && cb.rnr->rcvq == NULLBUF) {
  849. #ifdef useblock
  850.                 if (up->noblock & SOCK_NORXBLOCK) {
  851.                     errno = (Curproc->retval == EALARM) ? EALARM : EWOULDBLOCK;
  852.                     return -1;
  853.                 } else
  854. #endif
  855.                 if ((errno = kwait (up)) != 0)
  856.                     return -1;
  857.             }
  858.             if (cb.rnr == NULLRNR) {
  859.                 /* Connection went away */
  860.                 errno = ENOTCONN;
  861.                 return -1;
  862.             }
  863.             bp = dequeue (&cb.rnr->rcvq);
  864.             (void) ntohnr3 (&n3hdr, &bp);
  865.             cnt = len_p (bp);
  866.             if (from != NULLCHAR && fromlen != NULLINT
  867.              && *fromlen >= (int) sizeof (struct sockaddr_nr)) {
  868.                 remote.nr = (struct sockaddr_nr *) from;
  869.                 remote.nr->nr_family = AF_NETROM;
  870.                 /* The callsign of the local user is not part of
  871.                    NET/ROM level 3, so that field is not used here */
  872.                 memcpy (remote.nr->nr_addr.node, n3hdr.source, AXALEN);
  873.                 *fromlen = sizeof (struct sockaddr_nr);
  874.             }
  875.             break;
  876.         case TYPE_NETROML4:
  877.             while ((cb.nr4 = up->cb.nr4) != NULLNR4CB && (bp = recv_nr4 (cb.nr4, (int16) 0)) == NULLBUF) {
  878. #ifdef useblock
  879.                 if (up->noblock & SOCK_NORXBLOCK) {
  880.                     errno = (Curproc->retval == EALARM) ? EALARM : EWOULDBLOCK;
  881.                     return -1;
  882.                 } else
  883. #endif
  884.                 if ((errno = kwait (up)) != 0)
  885.                     return -1;
  886.             }
  887.             if (cb.nr4 == NULLNR4CB) {
  888.                 /* Connection went away */
  889.                 errno = ENOTCONN;
  890.                 return -1;
  891.             }
  892.             if (bp == NULLBUF)
  893.                 return 0;
  894.             cnt = bp->cnt;
  895.             break;
  896. #endif
  897.         default:
  898.             break;
  899.     }
  900.     if (bpp != NULLBUFP)
  901.         *bpp = bp;
  902.     else
  903.         free_p (bp);
  904.     return cnt;
  905. }
  906.  
  907.  
  908.  
  909. /* Low level send routine; user supplies mbuf for transmission. More
  910.  * efficient than send() or sendto(), the higher level interfaces.
  911.  * The "to" and "tolen" parameters are ignored on connection-oriented
  912.  * sockets.
  913.  *
  914.  * In case of error, bp is freed so the caller doesn't have to worry about it.
  915.  */
  916. int
  917. send_mbuf (
  918. int s,                /* Socket index */
  919. struct mbuf *bp,        /* Buffer to send */
  920. int flags,            /* not currently used */
  921. char *to,            /* Destination, only for datagrams */
  922. int tolen            /* Length of destination */
  923. ) {
  924. register struct usock *up;
  925. union cb cb;
  926. union sp local, remote;
  927. struct socket lsock, fsock;
  928. int cnt;
  929.  
  930.     if ((up = itop (s)) == NULLUSOCK) {
  931.         free_p (bp);
  932.         errno = EBADF;
  933.         return -1;
  934.     }
  935. #ifndef    notdef
  936.     if (up->obuf != NULLBUF) {
  937.         /* If there's unflushed output, send it.
  938.          * Note the importance of clearing up->obuf
  939.          * before the recursive call!
  940.          */
  941.         struct mbuf *bp1;
  942.  
  943.         bp1 = up->obuf;
  944.         up->obuf = NULLBUF;
  945.         (void) send_mbuf (s, bp1, flags, to, tolen);
  946.     }
  947. #endif
  948.     if (up->name == NULLCHAR) {
  949.         /* Automatic local name assignment for datagram sockets */
  950.         switch (up->type) {
  951.             case TYPE_LOCAL_STREAM:
  952.             case TYPE_LOCAL_DGRAM:
  953.                 break;    /* no op */
  954.             case TYPE_UDP:
  955.             case TYPE_RAW:
  956.                 autobind (s, AF_INET);
  957.                 break;
  958. #ifdef    AX25
  959.             case TYPE_AX25UI:
  960.                 autobind (s, AF_AX25);
  961.                 break;
  962. #endif
  963. #ifdef    NETROM
  964.             case TYPE_NETROML3:
  965.             case TYPE_NETROML4:
  966.                 autobind (s, AF_NETROM);
  967.                 break;
  968. #endif
  969.             default:
  970.                 free_p (bp);
  971.                 errno = ENOTCONN;
  972.                 return -1;
  973.         }
  974.     }
  975.     cnt = len_p (bp);
  976.     switch (up->type) {
  977.         case TYPE_LOCAL_DGRAM:
  978.             if (up->cb.local->peer == NULLUSOCK) {
  979.                 free_p (bp);
  980.                 errno = ENOTCONN;
  981.                 return -1;
  982.             }
  983.             enqueue (&up->cb.local->peer->cb.local->q, bp);
  984.             ksignal (up->cb.local->peer, 0);
  985.             /* If high water mark has been reached, block */
  986.             while (up->cb.local->peer != NULLUSOCK &&
  987.                    len_q (up->cb.local->peer->cb.local->q) >=
  988.                    up->cb.local->peer->cb.local->hiwat) {
  989.                 if (up->noblock & SOCK_NOTXBLOCK) {
  990.                     errno = EWOULDBLOCK;
  991.                     return -1;
  992.                 } else if ((errno = kwait (up->cb.local->peer)) != 0) {
  993.                     return -1;
  994.                 }
  995.             }
  996.             if (up->cb.local->peer == NULLUSOCK) {
  997.                 errno = ENOTCONN;
  998.                 return -1;
  999.             }
  1000.             break;
  1001.         case TYPE_LOCAL_STREAM:
  1002.             if (up->cb.local->peer == NULLUSOCK) {
  1003.                 free_p (bp);
  1004.                 errno = ENOTCONN;
  1005.                 return -1;
  1006.             }
  1007.             append (&up->cb.local->peer->cb.local->q, bp);
  1008.             ksignal (up->cb.local->peer, 0);
  1009.             /* If high water mark has been reached, block */
  1010.             while (up->cb.local->peer != NULLUSOCK &&
  1011.                    len_p (up->cb.local->peer->cb.local->q) >=
  1012.                    up->cb.local->peer->cb.local->hiwat) {
  1013.                 if (up->noblock & SOCK_NOTXBLOCK) {
  1014.                     errno = EWOULDBLOCK;
  1015.                     return -1;
  1016.                 } else if ((errno = kwait (up->cb.local->peer)) != 0) {
  1017.                     return -1;
  1018.                 }
  1019.             }
  1020.             if (up->cb.local->peer == NULLUSOCK) {
  1021.                 errno = ENOTCONN;
  1022.                 return -1;
  1023.             }
  1024.             break;
  1025.         case TYPE_TCP:
  1026.             if ((cb.tcb = up->cb.tcb) == NULLTCB) {
  1027.                 free_p (bp);
  1028.                 errno = ENOTCONN;
  1029.                 return -1;
  1030.             }
  1031.             cnt = send_tcp (cb.tcb, bp);
  1032.  
  1033.             while ((cb.tcb = up->cb.tcb) != NULLTCB &&
  1034.                    cb.tcb->sndcnt > cb.tcb->window) {
  1035.                 /* Send queue is full */
  1036.                 if (up->noblock & SOCK_NOTXBLOCK) {
  1037.                     errno = EWOULDBLOCK;
  1038.                     return -1;
  1039.                 } else if ((errno = kwait (up)) != 0) {
  1040.                     return -1;
  1041.                 }
  1042.             }
  1043.             if (cb.tcb == NULLTCB) {
  1044.                 errno = ENOTCONN;
  1045.                 return -1;
  1046.             }
  1047.             break;
  1048.         case TYPE_UDP:
  1049.             local.in = (struct sockaddr_in *) up->name;
  1050.             lsock.address = local.in->sin_addr.s_addr;
  1051.             lsock.port = local.in->sin_port;
  1052.             if (to != NULLCHAR)
  1053.                 remote.in = (struct sockaddr_in *) to;
  1054.             else if (up->peername != NULLCHAR)
  1055.                 remote.in = (struct sockaddr_in *) up->peername;
  1056.             else {
  1057.                 errno = ENOTCONN;
  1058.                 return -1;
  1059.             }
  1060.             fsock.address = remote.in->sin_addr.s_addr;
  1061.             fsock.port = remote.in->sin_port;
  1062.             (void) send_udp (&lsock, &fsock, 0, 0, bp, 0, 0, 0);
  1063.             break;
  1064.         case TYPE_RAW:
  1065.             local.in = (struct sockaddr_in *) up->name;
  1066.             if (to != NULLCHAR)
  1067.                 remote.in = (struct sockaddr_in *) to;
  1068.             else if (up->peername != NULLCHAR)
  1069.                 remote.in = (struct sockaddr_in *) up->peername;
  1070.             else {
  1071.                 errno = ENOTCONN;
  1072.                 return -1;
  1073.             }
  1074.             (void) ip_send (local.in->sin_addr.s_addr, remote.in->sin_addr.s_addr,
  1075.                 (char) up->cb.rip->protocol, 0, 0, bp, 0, 0, 0);
  1076.             break;
  1077. #ifdef    AX25
  1078.         case TYPE_AX25I:
  1079.             if ((cb.ax25 = up->cb.ax25) == NULLAX25) {
  1080.                 free_p (bp);
  1081.                 errno = ENOTCONN;
  1082.                 return -1;
  1083.             }
  1084.             (void) send_ax25 (cb.ax25, bp, PID_NO_L3);
  1085.  
  1086.             while ((cb.ax25 = up->cb.ax25) != NULLAX25 &&
  1087.                    len_q (cb.ax25->txq) * cb.ax25->paclen > cb.ax25->window) {
  1088.                 if (up->noblock & SOCK_NOTXBLOCK) {
  1089.                     errno = EWOULDBLOCK;
  1090.                     return -1;
  1091.                 } else if ((errno = kwait (up)) != 0) {
  1092.                     return -1;
  1093.                 }
  1094.             }
  1095.             if (cb.ax25 == NULLAX25) {
  1096.                 errno = EBADF;
  1097.                 return -1;
  1098.             }
  1099.             break;
  1100.         case TYPE_AX25UI:
  1101.             local.ax = (struct sockaddr_ax *) up->name;
  1102.             if (to != NULLCHAR)
  1103.                 remote.ax = (struct sockaddr_ax *) to;
  1104.             else if (up->peername != NULLCHAR)
  1105.                 remote.ax = (struct sockaddr_ax *) up->peername;
  1106.             else {
  1107.                 errno = ENOTCONN;
  1108.                 return -1;
  1109.             }
  1110.             (void) ax_output (if_lookup (remote.ax->iface), remote.ax->ax25_addr,
  1111.                 local.ax->ax25_addr, PID_NO_L3, bp);
  1112.             break;
  1113. #endif
  1114. #ifdef NETROM
  1115.         case TYPE_NETROML3:
  1116.             /* This should never happen, since the TCP code will peek at the
  1117.              * interface mtu ! - WG7J
  1118.              */
  1119.             if (len_p (bp) > NR4MAXINFO) {
  1120.                 free_p (bp);
  1121.                 errno = EMSGSIZE;
  1122.                 return -1;
  1123.             }
  1124.             local.nr = (struct sockaddr_nr *) up->name;
  1125.             if (to != NULLCHAR)
  1126.                 remote.nr = (struct sockaddr_nr *) to;
  1127.             else if (up->peername != NULLCHAR)
  1128.                 remote.nr = (struct sockaddr_nr *) up->peername;
  1129.             else {
  1130.                 errno = ENOTCONN;
  1131.                 return -1;
  1132.             }
  1133.             /* The NETROM username is always ignored in outgoing traffic */
  1134.             nr_sendraw (remote.nr->nr_addr.node,
  1135.                 (unsigned) (int) up->cb.rnr->protocol, (unsigned) (int) up->cb.rnr->protocol, bp);
  1136.             break;
  1137.         case TYPE_NETROML4:
  1138.             if ((cb.nr4 = up->cb.nr4) == NULLNR4CB) {
  1139.                 free_p (bp);
  1140.                 errno = ENOTCONN;
  1141.                 return -1;
  1142.             }
  1143. #ifdef notdef
  1144.             /* since I now fragment nr4 packets in send_nr4(),
  1145.              * don't worry, be happy :-) - WG7J
  1146.              */
  1147.             if (len_p (bp) > NR4MAXINFO) {    /* reject big packets */
  1148.                 free_p (bp);
  1149.                 errno = EMSGSIZE;
  1150.                 return -1;
  1151.             }
  1152. #endif
  1153.             (void) send_nr4 (cb.nr4, bp);
  1154.  
  1155.             while ((cb.nr4 = up->cb.nr4) != NULLNR4CB &&
  1156.                    cb.nr4->nbuffered >= cb.nr4->window) {
  1157.                 if (up->noblock & SOCK_NOTXBLOCK) {
  1158.                     errno = EWOULDBLOCK;
  1159.                     return -1;
  1160.                 } else if ((errno = kwait (up)) != 0) {
  1161.                     errno = EINTR;
  1162.                     return -1;
  1163.                 }
  1164.             }
  1165.             if (cb.nr4 == NULLNR4CB) {
  1166.                 errno = EBADF;
  1167.                 return -1;
  1168.             }
  1169.             break;
  1170. #endif
  1171.         default:
  1172.             break;
  1173.     }
  1174.     return cnt;
  1175. }
  1176.  
  1177.  
  1178.  
  1179. /* Return local name passed in an earlier bind() call */
  1180. int
  1181. getsockname (
  1182. int s,                /* Socket index */
  1183. char *name,            /* Place to stash name */
  1184. int *namelen            /* Length of same */
  1185. ) {
  1186. register struct usock *up;
  1187.  
  1188.     if ((up = itop (s)) == NULLUSOCK) {
  1189.         errno = EBADF;
  1190.         return -1;
  1191.     }
  1192.     if (name == NULLCHAR || namelen == (int *) NULL) {
  1193.         errno = EFAULT;
  1194.         return -1;
  1195.     }
  1196.     if (up->name == NULLCHAR) {
  1197.         /* Not bound yet */
  1198.         *namelen = 0;
  1199.         *name = 0;
  1200.         return 0;
  1201.     }
  1202.     if (up->name != NULLCHAR) {
  1203.         *namelen = min (*namelen, up->namelen);
  1204.         memcpy (name, up->name, (size_t) * namelen);
  1205.     }
  1206.     return 0;
  1207. }
  1208.  
  1209.  
  1210.  
  1211. /* Get remote name, returning result of earlier connect() call. */
  1212. int
  1213. getpeername (
  1214. int s,                /* Socket index */
  1215. char *peername,            /* Place to stash name */
  1216. int *peernamelen        /* Length of same */
  1217. ) {
  1218. register struct usock *up;
  1219.  
  1220.     if ((up = itop (s)) == NULLUSOCK) {
  1221.         errno = EBADF;
  1222.         return -1;
  1223.     }
  1224.     if (up->peername == NULLCHAR) {
  1225.         errno = ENOTCONN;
  1226.         return -1;
  1227.     }
  1228.     if (peername == NULLCHAR || peernamelen == (int *) NULL) {
  1229.         errno = EFAULT;
  1230.         return -1;
  1231.     }
  1232.     *peernamelen = min (*peernamelen, up->peernamelen);
  1233.     memcpy (peername, up->peername, (size_t) * peernamelen);
  1234.     return 0;
  1235. }
  1236.  
  1237.  
  1238.  
  1239. /* Return length of protocol queue, either send or receive. */
  1240. int
  1241. socklen (
  1242. int s,                /* Socket index */
  1243. int rtx                /* 0 = receive queue, 1 = transmit queue */
  1244. ) {
  1245. register struct usock *up;
  1246. int len = -1;
  1247.  
  1248.     if ((up = itop (s)) == NULLUSOCK) {
  1249.         errno = EBADF;
  1250.         return -1;
  1251.     }
  1252.     if (up->cb.p == NULLCHAR) {
  1253.         errno = ENOTCONN;
  1254.         return -1;
  1255.     }
  1256.     if (rtx < 0 || rtx > 1) {
  1257.         errno = EINVAL;
  1258.         return -1;
  1259.     }
  1260.     switch (up->type) {
  1261.         case TYPE_LOCAL_DGRAM:
  1262.             switch (rtx) {
  1263.                 case 0:
  1264.                     len = len_q (up->cb.local->q);
  1265.                     break;
  1266.                 case 1:
  1267.                     if (up->cb.local->peer != NULLUSOCK)
  1268.                         len = len_q (up->cb.local->peer->cb.local->q);
  1269.                     break;
  1270.                 default:
  1271.                     break;
  1272.             }
  1273.             break;
  1274.         case TYPE_LOCAL_STREAM:
  1275.             switch (rtx) {
  1276.                 case 0:
  1277.                     len = len_p (up->cb.local->q) + len_p (up->ibuf);
  1278.                     break;
  1279.                 case 1:
  1280.                     if (up->cb.local->peer != NULLUSOCK)
  1281.                         len = len_p (up->cb.local->peer->cb.local->q)
  1282.                             + len_p (up->obuf);
  1283.                     break;
  1284.                 default:
  1285.                     break;
  1286.             }
  1287.             break;
  1288.         case TYPE_TCP:
  1289.             switch (rtx) {
  1290.                 case 0:
  1291.                     len = up->cb.tcb->rcvcnt + len_p (up->ibuf);
  1292.                     break;
  1293.                 case 1:
  1294.                     len = up->cb.tcb->sndcnt + len_p (up->obuf);
  1295.                     break;
  1296.                 default:
  1297.                     break;
  1298.             }
  1299.             break;
  1300.         case TYPE_UDP:
  1301.             switch (rtx) {
  1302.                 case 0:
  1303.                     len = up->cb.udp->rcvcnt;
  1304.                     break;
  1305.                 case 1:
  1306.                     len = 0;
  1307.                     break;
  1308.                 default:
  1309.                     break;
  1310.             }
  1311.             break;
  1312. #ifdef    AX25
  1313.         case TYPE_AX25I:
  1314.             switch (rtx) {
  1315.                 case 0:
  1316.                     len = len_p (up->cb.ax25->rxq) + len_p (up->ibuf);
  1317.                     break;
  1318.                 case 1:    /* Number of packets, not bytes */
  1319.                     len = len_q (up->cb.ax25->txq);
  1320.                     if (up->obuf != NULLBUF)
  1321.                         len++;
  1322.                     break;
  1323.                 default:
  1324.                     break;
  1325.             }
  1326.             break;
  1327. #ifdef notdef
  1328.         case TYPE_AX25UI:
  1329.             switch (rtx) {
  1330.                 case 0:
  1331.                     len = len_q (Bcq);
  1332.                     break;
  1333.                 case 1:
  1334.                     len = 0;
  1335.                     break;
  1336.                 default:
  1337.                     break;
  1338.             }
  1339.             break;
  1340. #endif /* notdef */
  1341. #endif
  1342. #ifdef NETROM
  1343.         case TYPE_NETROML3:
  1344.             switch (rtx) {
  1345.                 case 0:
  1346.                     len = len_q (up->cb.rnr->rcvq);
  1347.                     break;
  1348.                 case 1:
  1349.                     len = 0;
  1350.                     break;
  1351.                 default:
  1352.                     break;
  1353.             }
  1354.             break;
  1355.         case TYPE_NETROML4:
  1356.             switch (rtx) {
  1357.                 case 0:
  1358.                     len = len_p (up->cb.nr4->rxq) + len_p (up->ibuf);
  1359.                     break;
  1360.                 case 1:    /* Number of packets, not bytes */
  1361.                     len = len_q (up->cb.nr4->txq);
  1362.                     if (up->obuf != NULLBUF)
  1363.                         len++;
  1364.                     break;
  1365.                 default:
  1366.                     break;
  1367.             }
  1368.             break;
  1369. #endif
  1370.         case TYPE_RAW:
  1371.             switch (rtx) {
  1372.                 case 0:
  1373.                     len = len_q (up->cb.rip->rcvq);
  1374.                     break;
  1375.                 case 1:
  1376.                     len = 0;
  1377.                     break;
  1378.                 default:
  1379.                     break;
  1380.             }
  1381.             break;
  1382.         default:
  1383.             break;
  1384.     }
  1385.     return len;
  1386. }
  1387.  
  1388.  
  1389.  
  1390. /* Force retransmission. Valid only for connection-oriented sockets. */
  1391. int
  1392. sockkick (
  1393. int s                /* Socket index */
  1394. ) {
  1395. register struct usock *up;
  1396.  
  1397.     if ((up = itop (s)) == NULLUSOCK) {
  1398.         errno = EBADF;
  1399.         return -1;
  1400.     }
  1401.     if (up->type == TYPE_LOCAL_STREAM || up->type == TYPE_LOCAL_DGRAM) {
  1402.         errno = EINVAL;
  1403.         return -1;
  1404.     }
  1405.     if (up->cb.p == NULLCHAR) {
  1406.         errno = ENOTCONN;
  1407.         return -1;
  1408.     }
  1409.     switch (up->type) {
  1410.         case TYPE_TCP:
  1411.             (void) kick_tcp (up->cb.tcb);
  1412.             break;
  1413. #ifdef    AX25
  1414.         case TYPE_AX25I:
  1415.             (void) kick_ax25 (up->cb.ax25);
  1416.             break;
  1417. #endif
  1418. #ifdef NETROM
  1419.         case TYPE_NETROML4:
  1420.             (void) kick_nr4 (up->cb.nr4);
  1421.             break;
  1422. #endif
  1423.         default:
  1424.             /* Datagram sockets can't be kicked */
  1425.             errno = EOPNOTSUPP;
  1426.             return -1;
  1427.     }
  1428.     return 0;
  1429. }
  1430.  
  1431.  
  1432.  
  1433. /* Change owner of socket, return previous owner */
  1434. struct proc *
  1435. sockowner (
  1436. int s,                /* Socket index */
  1437. struct proc *newowner        /* Process table address of new owner */
  1438. ) {
  1439. register struct usock *up;
  1440. struct proc *pp;
  1441.  
  1442.     if ((up = itop (s)) == NULLUSOCK) {
  1443.         errno = EBADF;
  1444.         return NULLPROC;
  1445.     }
  1446.     pp = up->owner;
  1447.     if (newowner != NULLPROC)
  1448.         up->owner = newowner;
  1449.     return pp;
  1450. }
  1451.  
  1452.  
  1453.  
  1454. /* Close down a socket three ways. Type 0 means "no more receives"; this
  1455.  * replaces the incoming data upcall with a routine that discards further
  1456.  * data. Type 1 means "no more sends", and obviously corresponds to sending
  1457.  * a TCP FIN. Type 2 means "no more receives or sends". This I interpret
  1458.  * as "abort the connection".
  1459.  */
  1460. int
  1461. shutdown (
  1462. int s,                /* Socket index */
  1463. int how                /* (see above) */
  1464. ) {
  1465. register struct usock *up;
  1466.  
  1467.     if ((up = itop (s)) == NULLUSOCK) {
  1468.         errno = EBADF;
  1469.         return -1;
  1470.     }
  1471.     if (up->cb.p == NULLCHAR) {
  1472.         errno = ENOTCONN;
  1473.         return -1;
  1474.     }
  1475.     switch (up->type) {
  1476.         case TYPE_LOCAL_DGRAM:
  1477.         case TYPE_LOCAL_STREAM:
  1478.             if (up->cb.local->q == NULLBUF)
  1479.                 close_s (s);
  1480.             else
  1481.                 up->cb.local->flags = LOC_SHUTDOWN;
  1482.             break;
  1483.         case TYPE_TCP:
  1484.             switch (how) {
  1485.                 case 0:    /* No more receives -- replace upcall */
  1486.                     up->cb.tcb->r_upcall = trdiscard;
  1487.                     break;
  1488.                 case 1:    /* Send EOF */
  1489.                     (void) close_tcp (up->cb.tcb);
  1490.                     break;
  1491.                 case 2:    /* Blow away TCB */
  1492.                     reset_tcp (up->cb.tcb);
  1493.                     up->cb.tcb = NULLTCB;
  1494.                     break;
  1495.                 default:
  1496.                     break;
  1497.             }
  1498.             break;
  1499. #ifdef    AX25
  1500. #ifdef notdef
  1501.         case TYPE_AX25UI:
  1502.             close_s (s);
  1503.             break;
  1504. #endif
  1505.         case TYPE_AX25I:
  1506.             switch (how) {
  1507.                 case 0:
  1508.                 case 1:    /* Attempt regular disconnect */
  1509.                     (void) disc_ax25 (up->cb.ax25);
  1510.                     break;
  1511.                 case 2:    /* Blow it away */
  1512.                     (void) reset_ax25 (up->cb.ax25);
  1513.                     up->cb.ax25 = NULLAX25;
  1514.                     break;
  1515.                 default:
  1516.                     break;
  1517.             }
  1518.             break;
  1519. #endif
  1520. #ifdef    NETROM
  1521.         case TYPE_NETROML3:
  1522.             close_s (s);
  1523.             break;
  1524.         case TYPE_NETROML4:
  1525.             switch (how) {
  1526.                 case 0:
  1527.                 case 1:    /* Attempt regular disconnect */
  1528.                     disc_nr4 (up->cb.nr4);
  1529.                     break;
  1530.                 case 2:    /* Blow it away */
  1531.                     reset_nr4 (up->cb.nr4);
  1532.                     up->cb.nr4 = NULLNR4CB;
  1533.                     break;
  1534.                 default:
  1535.                     break;
  1536.             }
  1537.             break;
  1538. #endif
  1539.         case TYPE_RAW:
  1540.         case TYPE_UDP:
  1541.             close_s (s);
  1542.             break;
  1543.         default:
  1544.             errno = EOPNOTSUPP;
  1545.             return -1;
  1546.     }
  1547.     ksignal (up, 0);
  1548.     return 0;
  1549. }
  1550.  
  1551.  
  1552.  
  1553. /* Close a socket, freeing it for reuse. Try to do a graceful close on a
  1554.  * TCP socket, if possible
  1555.  */
  1556. int
  1557. close_s (
  1558. int s                /* Socket index */
  1559. ) {
  1560. register struct usock *up;
  1561.  
  1562.     if (s == -1)
  1563.         return 0;
  1564.     if ((up = itop (s)) == NULLUSOCK) {
  1565.         errno = EBADF;
  1566.         return -1;
  1567.     }
  1568.     if (--up->refcnt > 0)
  1569.         return 0;    /* Others are still using it */
  1570.     usflush (s);
  1571.     if (up->ibuf != NULLBUF) {
  1572.         free_p (up->ibuf);
  1573.         up->ibuf = NULLBUF;
  1574.     }
  1575.     switch (up->type) {
  1576.         case TYPE_LOCAL_STREAM:
  1577.         case TYPE_LOCAL_DGRAM:
  1578.             if (up->cb.local->peer != NULLUSOCK) {
  1579.                 up->cb.local->peer->cb.local->peer = NULLUSOCK;
  1580.                 ksignal (up->cb.local->peer, 0);
  1581.             }
  1582.             free_q (&up->cb.local->q);
  1583.             free (up->cb.local);
  1584.             break;
  1585.         case TYPE_TCP:
  1586.             if (up->cb.tcb != NULLTCB) {    /* In case it's been reset */
  1587.                 up->cb.tcb->r_upcall = trdiscard;
  1588.                 /* Tell the TCP_CLOSED upcall there's no more socket */
  1589.                 up->cb.tcb->user = -1;
  1590.                 if (up->cb.p)    /* forget this for null sockets */
  1591.                     (void) close_tcp (up->cb.tcb);
  1592.             }
  1593.             break;
  1594.         case TYPE_UDP:
  1595.             if (up->cb.udp != NULLUDP)
  1596.                 (void) del_udp (up->cb.udp);
  1597.             break;
  1598. #ifdef    AX25
  1599.         case TYPE_AX25I:
  1600.             if (up->cb.ax25 != NULLAX25) {
  1601.                 /* Tell the TCP_CLOSED upcall there's no more socket */
  1602.                 up->cb.ax25->user = -1;
  1603.                 (void) disc_ax25 (up->cb.ax25);
  1604.             }
  1605.             break;
  1606. #ifdef notdef
  1607.         case TYPE_AX25UI:
  1608.             Axui_sock = -1;
  1609.             free_q (&Bcq);
  1610.             ksignal (&Bcq, 0);    /* Unblock any reads */
  1611.             break;
  1612. #endif /* notdef */
  1613. #endif
  1614. #ifdef    NETROM
  1615.         case TYPE_NETROML3:
  1616.             del_rnr (up->cb.rnr);
  1617.             break;
  1618.         case TYPE_NETROML4:
  1619.             if (up->cb.nr4 != NULLNR4CB) {
  1620.                 /* Tell the TCP_CLOSED upcall there's no more socket */
  1621.                 up->cb.nr4->user = -1;
  1622.                 disc_nr4 (up->cb.nr4);
  1623.             }
  1624.             break;
  1625. #endif
  1626.         case TYPE_RAW:
  1627.             del_ip (up->cb.rip);
  1628.             break;
  1629.         default:
  1630.             errno = EOPNOTSUPP;
  1631.             return -1;
  1632.     }
  1633. #ifdef    LZW
  1634.     if (up->zout != NULLLZW || up->zin != NULLLZW)
  1635.         lzwfree (up);
  1636. #endif
  1637.     free (up->name);
  1638.     free (up->peername);
  1639.  
  1640.     up->cb.p = NULLCHAR;
  1641.     up->name = up->peername = NULLCHAR;
  1642.     up->type = NOTUSED;
  1643.     ksignal (up, 0);    /* Wake up anybody doing an accept() or recv() */
  1644. #ifdef LOOKSESSION
  1645.     if (up->look)        /* Alert the process looking at us */
  1646.         alert (up->look, ENOTCONN);
  1647. #endif
  1648.     return 0;
  1649. }
  1650.  
  1651.  
  1652.  
  1653. /* Increment reference count for specified socket */
  1654. int
  1655. usesock (int s)
  1656. {
  1657. struct usock *up;
  1658.  
  1659.     if ((up = itop (s)) == NULLUSOCK) {
  1660.         errno = EBADF;
  1661.         return -1;
  1662.     }
  1663.     up->refcnt++;
  1664.     return 0;
  1665. }
  1666.  
  1667.  
  1668.  
  1669. /* Blow away all sockets belonging to a certain process. Used by killproc(). */
  1670. void
  1671. freesock (struct proc *pp)
  1672. {
  1673. register struct usock *up;
  1674. register int i;
  1675.  
  1676.     for (i = SOCKBASE; i < Nusock + SOCKBASE; i++) {
  1677.         up = itop (i);
  1678.         if (up != NULLUSOCK && up->type != NOTUSED && up->owner == pp)
  1679.             (void) shutdown (i, 2);
  1680.     }
  1681. }
  1682.  
  1683.  
  1684.  
  1685. /* Start of internal subroutines */
  1686.  
  1687. /* Raw IP receive upcall routine */
  1688. static void
  1689. rip_recv (struct raw_ip *rp)
  1690. {
  1691.     ksignal (itop (rp->user), 1);
  1692.     kwait (NULL);
  1693. }
  1694.  
  1695.  
  1696.  
  1697. /* UDP receive upcall routine */
  1698. static void
  1699. s_urcall (struct iface *iface OPTIONAL, struct udp_cb *udp, int16 cnt OPTIONAL)
  1700. {
  1701.     ksignal (itop (udp->user), 1);
  1702.     kwait (NULL);
  1703. }
  1704.  
  1705.  
  1706.  
  1707. /* TCP receive upcall routine */
  1708. static void
  1709. s_trcall (struct tcb *tcb, int16 cnt OPTIONAL)
  1710. {
  1711.     /* Wake up anybody waiting for data, and let them run */
  1712.     ksignal (itop (tcb->user), 1);
  1713.     kwait (NULL);
  1714. }
  1715.  
  1716.  
  1717.  
  1718. /* TCP transmit upcall routine */
  1719. static void
  1720. s_ttcall (struct tcb *tcb, int16 cnt OPTIONAL)
  1721. {
  1722.     /* Wake up anybody waiting to send data, and let them run */
  1723.     ksignal (itop (tcb->user), 1);
  1724.     kwait (NULL);
  1725. }
  1726.  
  1727.  
  1728.  
  1729. /* TCP state change upcall routine */
  1730. static void
  1731. s_tscall (struct tcb *tcb, int old OPTIONAL, int new)
  1732. {
  1733. int s, ns;
  1734. struct usock *up, *nup, *oup;
  1735. union sp sp;
  1736.  
  1737.     s = tcb->user;
  1738.     oup = up = itop (s);
  1739.  
  1740.     switch (new) {
  1741.         case TCP_CLOSED:
  1742.             /* Clean up. If the user has already closed the socket,
  1743.              * then up will be null (s was set to -1 by the close routine).
  1744.              * If not, then this is an abnormal close (e.g., a reset)
  1745.              * and clearing out the pointer in the socket structure will
  1746.              * prevent any further operations on what will be a freed
  1747.              * control block. Also wake up anybody waiting on events
  1748.              * related to this tcb so they will notice it disappearing.
  1749.              */
  1750.             if (up != NULLUSOCK) {
  1751.                 up->cb.tcb = NULLTCB;
  1752.                 up->errcodes[0] = tcb->reason;
  1753.                 up->errcodes[1] = tcb->type;
  1754.                 up->errcodes[2] = tcb->code;
  1755.             }
  1756.             (void) del_tcp (tcb);
  1757.             break;
  1758.         case TCP_SYN_RECEIVED:
  1759.             /* Handle an incoming connection. If this is a server TCB,
  1760.              * then we're being handed a "clone" TCB and we need to
  1761.              * create a new socket structure for it. In either case,
  1762.              * find out who we're talking to and wake up the guy waiting
  1763.              * for the connection.
  1764.              */
  1765.             if (tcb->flags.clone) {
  1766.                 /* Clone the socket */
  1767.                 ns = socket (AF_INET, SOCK_STREAM, 0);
  1768.                 nup = itop (ns);
  1769.                 if (up == NULLUSOCK)    /* shouldn't happen */
  1770.                     return;
  1771.                 if (nup == NULLUSOCK) {
  1772.                     log (-1, "Couldn't open socket!\n");
  1773.                     tcmdprintf ("Couldn't open socket!\n\007");
  1774.                     return;
  1775.                 }
  1776.                 ASSIGN (*nup, *up);
  1777.                 tcb->user = ns;
  1778.                 nup->cb.tcb = tcb;
  1779.                 /* Allocate new memory for the name areas */
  1780.                 nup->name = mallocw (SOCKSIZE);
  1781.                 nup->peername = mallocw (SOCKSIZE);
  1782.                 /* Store the new socket # in the old one */
  1783.                 up->rdysock = ns;
  1784.                 up = nup;
  1785.                 s = ns;
  1786.             } else {
  1787.                 /* Allocate space for the peer's name */
  1788.                 up->peername = mallocw (SOCKSIZE);
  1789.                 /* Store the old socket # in the old socket */
  1790.                 up->rdysock = s;
  1791.             }
  1792.             /* Load the addresses. Memory for the name has already
  1793.              * been allocated, either above or in the original bind.
  1794.              */
  1795.             sp.p = up->name;
  1796.             sp.in->sin_family = AF_INET;
  1797.             sp.in->sin_addr.s_addr = up->cb.tcb->conn.local.address;
  1798.             sp.in->sin_port = up->cb.tcb->conn.local.port;
  1799.             up->namelen = SOCKSIZE;
  1800.  
  1801.             sp.p = up->peername;
  1802.             sp.in->sin_family = AF_INET;
  1803.             sp.in->sin_addr.s_addr = up->cb.tcb->conn.remote.address;
  1804.             sp.in->sin_port = up->cb.tcb->conn.remote.port;
  1805.             up->peernamelen = SOCKSIZE;
  1806.  
  1807.             /* Wake up the guy accepting it, and let him run */
  1808.             ksignal (oup, 1);
  1809.             kwait (NULL);
  1810.             break;
  1811.         default:    /* Ignore all other state transitions */
  1812.             break;
  1813.     }
  1814.     ksignal (up, 0);    /* In case anybody's waiting */
  1815. }
  1816.  
  1817.  
  1818.  
  1819. /* Discard data received on a TCP connection. Used after a receive shutdown or
  1820.  * close_s until the TCB disappears.
  1821.  */
  1822. static void
  1823. trdiscard (struct tcb *tcb, int16 cnt)
  1824. {
  1825. struct mbuf *bp;
  1826.  
  1827.     (void) recv_tcp (tcb, &bp, (int16) cnt);
  1828.     free_p (bp);
  1829. }
  1830.  
  1831.  
  1832.  
  1833. #ifdef    AX25
  1834. /* AX.25 receive upcall */
  1835. void
  1836. s_arcall (struct ax25_cb *axp, int cnt OPTIONAL)
  1837. {
  1838. int ns;
  1839. struct usock *up, *nup, *oup;
  1840. union sp sp;
  1841.  
  1842.     up = itop (axp->user);
  1843.     /* When AX.25 data arrives for the first time the AX.25 listener
  1844.        is notified, if active. If the AX.25 listener is a server its
  1845.        socket is duplicated in the same manner as in s_tscall().
  1846.      */
  1847.     if (Axi_sock != -1 && axp->user == -1) {
  1848. #if 1
  1849.         if (addreq (axp->local, axp->iface->ipcall))
  1850.             return;
  1851. #endif
  1852.         oup = up = itop (Axi_sock);
  1853.         /* From now on, use the same upcalls as the listener */
  1854.         axp->t_upcall = up->cb.ax25->t_upcall;
  1855.         axp->r_upcall = up->cb.ax25->r_upcall;
  1856.         axp->s_upcall = up->cb.ax25->s_upcall;
  1857.         if (up->cb.ax25->flags.clone) {
  1858.             /* Clone the socket */
  1859.             ns = socket (AF_AX25, SOCK_STREAM, 0);
  1860.             nup = itop (ns);
  1861.             ASSIGN (*nup, *up);
  1862.             axp->user = ns;
  1863.             nup->cb.ax25 = axp;
  1864.             /* Allocate new memory for the name areas */
  1865.             nup->name = mallocw (sizeof (struct sockaddr_ax));
  1866.             nup->peername = mallocw (sizeof (struct sockaddr_ax));
  1867.  
  1868.             /* Store the new socket # in the old one */
  1869.             up->rdysock = ns;
  1870.             up = nup;
  1871.         } else {
  1872.             axp->user = Axi_sock;
  1873.             del_ax25 (up->cb.ax25);
  1874.             up->cb.ax25 = axp;
  1875.             /* Allocate space for the peer's name */
  1876.             up->peername = mallocw (sizeof (struct sockaddr_ax));
  1877.  
  1878.             /* Store the old socket # in the old socket */
  1879.             up->rdysock = Axi_sock;
  1880.         }
  1881.         /* Load the addresses. Memory for the name has already
  1882.          * been allocated, either above or in the original bind.
  1883.          */
  1884.         sp.p = up->name;
  1885.         sp.ax->sax_family = AF_AX25;
  1886.         memcpy (sp.ax->ax25_addr, axp->local, AXALEN);
  1887.         strncpy (sp.ax->iface, axp->iface->name, ILEN - 1);
  1888.         up->namelen = sizeof (struct sockaddr_ax);
  1889.  
  1890.         sp.p = up->peername;
  1891.         sp.ax->sax_family = AF_AX25;
  1892.         memcpy (sp.ax->ax25_addr, axp->remote, AXALEN);
  1893.         strncpy (sp.ax->iface, axp->iface->name, ILEN - 1);
  1894.         up->peernamelen = sizeof (struct sockaddr_ax);
  1895.  
  1896.         /* Wake up the guy accepting it, and let him run */
  1897.         ksignal (oup, 1);
  1898.         kwait (NULL);
  1899.         return;
  1900.     }
  1901.     /* Wake up anyone waiting, and let them run */
  1902.     ksignal (up, 1);
  1903.     kwait (NULL);
  1904. }
  1905.  
  1906.  
  1907.  
  1908. /* AX.25 transmit upcall */
  1909. void
  1910. s_atcall (struct ax25_cb *axp, int cnt OPTIONAL)
  1911. {
  1912.     /* Wake up anyone waiting, and let them run */
  1913.     ksignal (itop (axp->user), 1);
  1914.     kwait (NULL);
  1915. }
  1916.  
  1917.  
  1918.  
  1919. /* AX25 state change upcall routine */
  1920. void
  1921. s_ascall (register struct ax25_cb *axp, int old OPTIONAL, int new)
  1922. {
  1923. int s;
  1924. struct usock *up;
  1925.  
  1926.     s = axp->user;
  1927.     up = itop (s);
  1928.  
  1929.     switch (new) {
  1930.         case LAPB_DISCONNECTED:
  1931.             /* Clean up. If the user has already closed the socket,
  1932.              * then up will be null (s was set to -1 by the close routine).
  1933.              * If not, then this is an abnormal close (e.g., a reset)
  1934.              * and clearing out the pointer in the socket structure will
  1935.              * prevent any further operations on what will be a freed
  1936.              * control block. Also wake up anybody waiting on events
  1937.              * related to this block so they will notice it disappearing.
  1938.              */
  1939.             if (up != NULLUSOCK) {
  1940.                 up->errcodes[0] = axp->reason;
  1941.                 up->cb.ax25 = NULLAX25;
  1942.             }
  1943.             del_ax25 (axp);
  1944.             break;
  1945.         default:    /* Other transitions are ignored */
  1946.             break;
  1947.     }
  1948.     ksignal (up, 0);    /* In case anybody's waiting */
  1949. }
  1950. #endif
  1951.  
  1952.  
  1953.  
  1954. #ifdef NETROM
  1955. /* NET/ROM receive upcall routine */
  1956. static void
  1957. s_nrcall (struct nr4cb *cb, int16 cnt OPTIONAL)
  1958. {
  1959.     /* Wake up anybody waiting for data, and let them run */
  1960.     ksignal (itop (cb->user), 1);
  1961.     kwait (NULL);
  1962. }
  1963.  
  1964.  
  1965.  
  1966. /* NET/ROM transmit upcall routine */
  1967. static void
  1968. s_ntcall (struct nr4cb *cb, int16 cnt OPTIONAL)
  1969. {
  1970.     /* Wake up anybody waiting to send data, and let them run */
  1971.     /*    ksignal(itop(cb->user),1); */
  1972.     /* Quick-fix for sending wait problem - Dave Perry, VE3IFB */
  1973.     ksignal (itop (cb->user), 0);
  1974.     kwait (NULL);
  1975. }
  1976.  
  1977.  
  1978.  
  1979. /* NET/ROM state change upcall routine */
  1980. static void
  1981. s_nscall (struct nr4cb *cb, int old, int new)
  1982. {
  1983. int s, ns;
  1984. struct usock *up, *nup, *oup;
  1985. union sp sp;
  1986.  
  1987.     s = cb->user;
  1988.     oup = up = itop (s);
  1989.  
  1990.     if (new == NR4STDISC && up != NULLUSOCK) {
  1991.         /* Clean up. If the user has already closed the socket,
  1992.          * then up will be null (s was set to -1 by the close routine).
  1993.          * If not, then this is an abnormal close (e.g., a reset)
  1994.          * and clearing out the pointer in the socket structure will
  1995.          * prevent any further operations on what will be a freed
  1996.          * control block. Also wake up anybody waiting on events
  1997.          * related to this cb so they will notice it disappearing.
  1998.          */
  1999.         up->cb.nr4 = NULLNR4CB;
  2000.         up->errcodes[0] = (char) cb->dreason;
  2001.     }
  2002.     if (new == NR4STCON && old == NR4STDISC) {
  2003.         /* Handle an incoming connection. If this is a server cb,
  2004.          * then we're being handed a "clone" cb and we need to
  2005.          * create a new socket structure for it. In either case,
  2006.          * find out who we're talking to and wake up the guy waiting
  2007.          * for the connection.
  2008.          */
  2009.         if (!up)
  2010.             return;
  2011.         if (cb->clone) {
  2012.             /* Clone the socket */
  2013.             ns = socket (AF_NETROM, SOCK_SEQPACKET, 0);
  2014.             nup = itop (ns);
  2015.             ASSIGN (*nup, *up);
  2016.             cb->user = ns;
  2017.             nup->cb.nr4 = cb;
  2018.             cb->clone = 0;    /* to avoid getting here again */
  2019.             /* Allocate new memory for the name areas */
  2020.             nup->name = mallocw (sizeof (struct sockaddr_nr));
  2021.             nup->peername = mallocw (sizeof (struct sockaddr_nr));
  2022.  
  2023.             /* Store the new socket # in the old one */
  2024.             up->rdysock = ns;
  2025.             up = nup;
  2026.             s = ns;
  2027.         } else {
  2028.             /* Allocate space for the peer's name */
  2029.             up->peername = mallocw (sizeof (struct sockaddr_nr));
  2030.  
  2031.             /* Store the old socket # in the old socket */
  2032.             up->rdysock = s;
  2033.         }
  2034.         /* Load the addresses. Memory for the name has already
  2035.          * been allocated, either above or in the original bind.
  2036.          */
  2037.         sp.p = up->name;
  2038.         sp.nr->nr_family = AF_NETROM;
  2039.         ASSIGN (sp.nr->nr_addr, up->cb.nr4->local);
  2040.         up->namelen = sizeof (struct sockaddr_nr);
  2041.  
  2042.         sp.p = up->peername;
  2043.         sp.nr->nr_family = AF_NETROM;
  2044.         ASSIGN (sp.nr->nr_addr, up->cb.nr4->remote);
  2045.         up->peernamelen = sizeof (struct sockaddr_nr);
  2046.  
  2047.         /* Wake up the guy accepting it, and let him run */
  2048.         ksignal (oup, 1);
  2049.         kwait (NULL);
  2050.     }
  2051.     /* Ignore all other state transitions */
  2052.     ksignal (up, 0);    /* In case anybody's waiting */
  2053. }
  2054. #endif
  2055.  
  2056.  
  2057.  
  2058. /* Verify address family and length according to the socket type */
  2059. static int
  2060. checkaddr (int type, char *name, int namelen)
  2061. {
  2062. union sp sp;
  2063.  
  2064.     sp.p = name;
  2065.     /* Verify length and address family according to protocol */
  2066.     switch (type) {
  2067.         case TYPE_TCP:
  2068.         case TYPE_UDP:
  2069.             if (sp.in->sin_family != AF_INET || namelen != (int) sizeof (struct sockaddr_in))
  2070.                 return -1;
  2071.             break;
  2072. #ifdef    AX25
  2073.         case TYPE_AX25I:
  2074. #ifdef notdef
  2075.         case TYPE_AX25UI:
  2076. #endif
  2077.             if (sp.ax->sax_family != AF_AX25 || namelen != (int) sizeof (struct sockaddr_ax))
  2078.                 return -1;
  2079.             break;
  2080. #endif
  2081. #ifdef    NETROM
  2082.         case TYPE_NETROML3:
  2083.         case TYPE_NETROML4:
  2084.             if (sp.nr->nr_family != AF_NETROM || namelen != (int) sizeof (struct sockaddr_nr))
  2085.                 return -1;
  2086.             break;
  2087. #endif
  2088.         default:
  2089.             break;
  2090.     }
  2091.     return 0;
  2092. }
  2093.  
  2094.  
  2095.  
  2096. /* Issue an automatic bind of a local address */
  2097. static void
  2098. autobind (int s, int af)
  2099. {
  2100. char buf[MAXSOCKSIZE];
  2101. union sp sp;
  2102.  
  2103.     sp.p = buf;
  2104.     switch (af) {
  2105.         case AF_INET:
  2106.             sp.in->sin_family = AF_INET;
  2107.             sp.in->sin_addr.s_addr = INADDR_ANY;
  2108.             sp.in->sin_port = Lport++;
  2109.             (void) bind (s, sp.p, sizeof (struct sockaddr_in));
  2110.             break;
  2111. #ifdef    AX25
  2112.         case AF_AX25:
  2113.             sp.ax->sax_family = AF_AX25;
  2114.             memset (sp.ax->ax25_addr, '\0', AXALEN);
  2115.             memset (sp.ax->iface, '\0', ILEN);
  2116.             (void) bind (s, sp.p, sizeof (struct sockaddr_ax));
  2117.             break;
  2118. #endif
  2119. #ifdef    NETROM
  2120.         case AF_NETROM:
  2121.             sp.nr->nr_family = AF_NETROM;
  2122.             memcpy (sp.nr->nr_addr.user, Mycall, AXALEN);
  2123.             memcpy (sp.nr->nr_addr.node, Mycall, AXALEN);
  2124.             (void) bind (s, sp.p, sizeof (struct sockaddr_nr));
  2125.             break;
  2126. #endif
  2127.         default:
  2128.             break;
  2129.     }
  2130. }
  2131.  
  2132.  
  2133.  
  2134. unsigned short getnextport (void);
  2135.  
  2136. unsigned short
  2137. getnextport (void)
  2138. {
  2139.     return (Lport++);
  2140. }
  2141.  
  2142.  
  2143.  
  2144. int
  2145. socketalive (int s)
  2146. {
  2147. register struct usock *up;
  2148.  
  2149.     if ((up = itop (s)) == NULLUSOCK)
  2150.         return 0;
  2151.  
  2152.     if (!up->cb.p)
  2153.         return 0;
  2154.  
  2155.     if (up->cb.tcb == NULLTCB || up->cb.tcb->r_upcall == trdiscard)
  2156.         return 0;
  2157.  
  2158.     if (up->cb.local->peer->cb.local->peer == NULLUSOCK)
  2159.         return 0;
  2160.  
  2161.     return 1;
  2162. }
  2163.  
  2164.  
  2165. /* this is called by tipmail only ! - WG7J */
  2166. #ifdef TIPMAIL
  2167.  
  2168. /* Return a pair of mutually connected sockets in sv[0] and sv[1] */
  2169. int
  2170. socketpair (int af, int type, int protocol, int sv[])
  2171. {
  2172. struct usock *up0, *up1;
  2173.  
  2174.     if (sv == NULLINT) {
  2175.         errno = EFAULT;
  2176.         return -1;
  2177.     }
  2178.     if (af != AF_LOCAL) {
  2179.         errno = EAFNOSUPPORT;
  2180.         return -1;
  2181.     }
  2182.     if (type != SOCK_STREAM && type != SOCK_DGRAM) {
  2183.         errno = ESOCKTNOSUPPORT;
  2184.         return -1;
  2185.     }
  2186.     if ((sv[0] = socket (af, type, protocol)) == -1)
  2187.         return -1;
  2188.     if ((sv[1] = socket (af, type, protocol)) == -1) {
  2189.         close_s (sv[0]);
  2190.         return -1;
  2191.     }
  2192.     up0 = itop (sv[0]);
  2193.     up1 = itop (sv[1]);
  2194.     up0->cb.local->peer = up1;
  2195.     up1->cb.local->peer = up0;
  2196.     return sv[1];
  2197. }
  2198. #endif
  2199.